package service

import (
	"bytes"
	"context"
	"encoding/json"
	"fx_swift_forex/api"
	"fx_swift_forex/internal/model"
	"fx_swift_forex/pkg/code"
	"fx_swift_forex/pkg/global"
	"fx_swift_forex/pkg/internalerrors"
	"github.com/gogf/gf/v2/frame/g"
	"mime/multipart"
	"strconv"
)

// cc银行开户
func CreateAccounts(ctx context.Context, req *api.AccountReq) (string, error) {
	var (
		err     error
		baseUrl = global.ViperObj.GetString("forex.baseUrl") + "/v2/accounts/create"
		body    []byte
		obj     *api.AccountRes
		payload *bytes.Buffer
		writer  *multipart.Writer
	)
	payload, writer, err = operatorAccountData(req)
	if err != nil {
		return "", internalerrors.New(code.ErrUnknown, err.Error())
	}
	body, err = PostRequestToCC(ctx, baseUrl, writer.FormDataContentType(), payload)
	if err != nil {
		return "", internalerrors.New(code.ErrUnknown, err.Error())
	}
	if err = json.Unmarshal(body, &obj); err != nil {
		return "", internalerrors.New(code.ErrUnknown, err.Error())
	}
	g.Dump(obj)
	if _, err = global.GFDB.Ctx(ctx).Model("forex_accounts").Insert(&model.ForexAccounts{
		AccountId:                  obj.Id,
		AccountName:                obj.AccountName,
		YourReference:              obj.YourReference,
		Brand:                      obj.Brand,
		Status:                     obj.Status,
		Street:                     obj.Street,
		City:                       obj.City,
		StateOrProvince:            obj.StateOrProvince,
		Country:                    obj.Country,
		PostalCode:                 obj.PostalCode,
		SpreadTable:                obj.SpreadTable,
		LegalEntityType:            obj.LegalEntityType,
		IdentificationType:         obj.IdentificationType,
		IdentificationValue:        obj.IdentificationValue,
		ShortReference:             obj.ShortReference,
		ApiTrading:                 strconv.FormatBool(obj.ApiTrading),
		OnlineTrading:              strconv.FormatBool(obj.OnlineTrading),
		PhoneTrading:               strconv.FormatBool(obj.PhoneTrading),
		ProcessThirdPartyFunds:     strconv.FormatBool(obj.ProcessThirdPartyFunds),
		SettlementType:             obj.SettlementType,
		AgentOrReliance:            strconv.FormatBool(obj.AgentOrReliance),
		TermsAndConditionsAccepted: strconv.FormatBool(obj.TermsAndConditionsAccepted),
		BankAccountVerified:        obj.BankAccountVerified,
	}); err != nil {
		return "", internalerrors.New(code.ErrUnknown, err.Error())
	}
	return obj.Id, err
}

func operatorAccountData(reqObj *api.AccountReq) (*bytes.Buffer, *multipart.Writer, error) {
	var (
		err error
	)
	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("account_name", reqObj.AccountName)
	_ = writer.WriteField("legal_entity_type", reqObj.LegalEntityType)
	_ = writer.WriteField("street", reqObj.Street)
	_ = writer.WriteField("city", reqObj.City)
	_ = writer.WriteField("country", reqObj.Country)
	_ = writer.WriteField("your_reference", reqObj.YourReference)
	_ = writer.WriteField("identification_type", reqObj.IdentificationType)
	_ = writer.WriteField("identification_value", reqObj.IdentificationValue)
	if len(reqObj.PostalCode) > 0 {
		_ = writer.WriteField("postal_code", reqObj.PostalCode)
	}
	if len(reqObj.Brand) > 0 {
		_ = writer.WriteField("brand", reqObj.Brand)
	}
	if len(reqObj.PostalCode) > 0 {
		_ = writer.WriteField("status", reqObj.Status)
	}
	if len(reqObj.StateOrProvince) > 0 {
		_ = writer.WriteField("state_or_province", reqObj.StateOrProvince)
	}
	if len(reqObj.SpreadTable) > 0 {
		_ = writer.WriteField("spread_table", reqObj.SpreadTable)
	}
	if len(reqObj.ApiTrading) > 0 {
		_ = writer.WriteField("api_trading", reqObj.ApiTrading)
	}
	if len(reqObj.OnlineTrading) > 0 {
		_ = writer.WriteField("online_trading", reqObj.OnlineTrading)
	}
	if len(reqObj.PhoneTrading) > 0 {
		_ = writer.WriteField("phone_trading", reqObj.PhoneTrading)
	}
	if len(reqObj.TermsAndConditionsAccepted) > 0 {
		_ = writer.WriteField("terms_and_conditions_accepted", reqObj.TermsAndConditionsAccepted)
	}
	if err = writer.Close(); err != nil {
		return nil, nil, internalerrors.New(code.ErrUnknown, err.Error())
	}
	return payload, writer, err
}

// cc银行账户联系人
func CreateContacts(ctx context.Context, req *api.ContactsReq) error {
	var (
		err     error
		baseUrl = global.ViperObj.GetString("forex.baseUrl") + "/v2/contacts/create"
		body    []byte
		obj     *api.ContactsRes
		payload *bytes.Buffer
		writer  *multipart.Writer
	)
	payload, writer, err = operatorContactsData(req)
	if err != nil {
		return internalerrors.New(code.ErrUnknown, err.Error())
	}
	body, err = PostRequestToCC(ctx, baseUrl, writer.FormDataContentType(), payload)
	if err != nil {
		return internalerrors.New(code.ErrUnknown, err.Error())
	}
	if err = json.Unmarshal(body, &obj); err != nil {
		return internalerrors.New(code.ErrUnknown, err.Error())
	}
	g.Dump(obj)
	if _, err = global.GFDB.Ctx(ctx).Model("forex_contacts").Insert(&model.ForexContacts{
		AccountId:         obj.AccountId,
		AccountName:       obj.AccountName,
		YourReference:     obj.YourReference,
		ContactsId:        obj.Id,
		Status:            obj.Status,
		LoginId:           obj.LoginId,
		FirstName:         obj.FirstName,
		LastName:          obj.LastName,
		Locale:            obj.Locale,
		TimeZone:          obj.Timezone,
		EmailAddress:      obj.EmailAddress,
		MobilePhoneNumber: obj.MobilePhoneNumber,
		PhoneNumber:       obj.PhoneNumber,
		DateOfBirth:       obj.DateOfBirth,
	}); err != nil {
		return internalerrors.New(code.ErrUnknown, err.Error())
	}
	return err
}

func operatorContactsData(reqObj *api.ContactsReq) (*bytes.Buffer, *multipart.Writer, error) {
	var (
		err error
	)
	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("account_id", reqObj.AccountId)
	_ = writer.WriteField("first_name", reqObj.FirstName)
	_ = writer.WriteField("last_name", reqObj.LastName)
	_ = writer.WriteField("email_address", reqObj.EmailAddress)
	_ = writer.WriteField("phone_number", reqObj.PhoneNumber)
	_ = writer.WriteField("your_reference", reqObj.YourReference)
	_ = writer.WriteField("date_of_birth", reqObj.DateOfBirth)
	_ = writer.WriteField("status", reqObj.Status)
	if len(reqObj.MobilePhoneNumber) > 0 {
		_ = writer.WriteField("mobile_phone_number", reqObj.MobilePhoneNumber)
	}
	if len(reqObj.LoginId) > 0 {
		_ = writer.WriteField("login_id", reqObj.LoginId)
	}
	if len(reqObj.Locale) > 0 {
		_ = writer.WriteField("locale", reqObj.Locale)
	}
	if len(reqObj.TimeZone) > 0 {
		_ = writer.WriteField("time_zone", reqObj.TimeZone)
	}
	if err = writer.Close(); err != nil {
		return nil, nil, internalerrors.New(code.ErrUnknown, err.Error())
	}
	return payload, writer, err
}
